#include "userGame.h"

const uint8_t gamebuinoLogo[]=
{
//	84,10, //width and height
//0X3,0XE1,0X81,0X86,0X7F,0X3E,0X18,0X6D,0X83,0XF,0XF,
//0XE,0X1,0X83,0X86,0X60,0X33,0X18,0X6D,0XC3,0X19,0X8F,
//0X18,0X3,0XC3,0X8E,0X60,0X33,0X18,0X6D,0XE3,0X30,0XCF,
//0X18,0X3,0XC3,0X9E,0X60,0X36,0X30,0XCD,0XE3,0X60,0XCF,
//0X30,0X6,0XC7,0X9E,0X7E,0X3E,0X30,0XCD,0XB3,0X60,0XCF,
//0X30,0XC,0XC6,0XF6,0X60,0X33,0X30,0XD9,0XB6,0X60,0XCF,
//0X33,0XCF,0XCC,0XF6,0X60,0X61,0XB0,0XDB,0X1E,0X60,0XCF,
//0X30,0XD8,0X6C,0XE6,0XC0,0X61,0XB0,0XDB,0X1E,0X61,0X8F,
//0X19,0X98,0X6C,0XC6,0XC0,0X63,0XB1,0X9B,0XE,0X33,0XF,
//0XF,0XB0,0X78,0XC6,0XFF,0X7E,0X1F,0X1B,0X6,0X1E,0XF, 
84,16,	
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x01,0xF0,0xFF,0xC3,0x00,0xC3,0xC0,0x00,0xC3,0x08,0x00,0x01,0xFD,0xFF,0xC3,
0x03,0xF3,0xF3,0xF1,0xCF,0x3E,0x00,0x01,0xFD,0xFF,0xC7,0x07,0xF7,0xFB,0xF7,0xDE,
0x7E,0x00,0x03,0x9D,0xCE,0x07,0x0F,0x37,0x3B,0xCF,0xBE,0x7E,0x00,0x03,0xFD,0xCE,
0x07,0x0E,0x07,0x3B,0xEF,0xBE,0xEE,0x00,0x03,0xF9,0x8E,0xF6,0x0E,0x07,0x3F,0x73,
0x8E,0xEE,0x00,0x03,0x1F,0x8C,0xFE,0x0E,0x76,0x7E,0x73,0x8C,0xEE,0x00,0x07,0xFF,
0x9C,0x0F,0xEF,0xFF,0xF7,0xE3,0x0C,0xFE,0x00,0x07,0xFB,0x9C,0x0F,0xE7,0xEF,0xE7,
0xE3,0x1C,0x7C,0x00,0x07,0xF3,0x1C,0x0F,0xE3,0x8F,0xC1,0xC3,0x1C,0x38,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};




Game gb;
void Game::begin() {
	timePerFrame = 50;
//	nextFrameMillis = 5000;
//	frameCount = 0;
	frameEndMicros = 1;
	startMenuTimer = 255;
  readSettings();
	//init everything
	display.begin();
	
	display.setBackLight(BACK_LIGHT_YELLOW);
	//要让屏幕可以显示字需添加display设置
	display.fontSize = 1;
	display.textWrap = false;
	display.persistence = false;
	display.setColor(BLACK);
	display.setFont(font5x7);
	//默认值设为0，关闭屏幕下方气泡框
	popupTimeLeft=0;	
	//显示模式设置为绘图模式
	state=DIS_STATE_DRAW;
	
	//菜单内容初始化
	menuactiveItem=0;
	menuItemNumber=0;
	menuItemList[0]=menuItemStr0;
	menuItemList[1]=menuItemStr1;
	menuItemList[2]=menuItemStr2;
	menuItemList[3]=menuItemStr3;
	menuItemList[4]=menuItemStr4;
	menuItemList[5]=menuItemStr5;
	menuItemList[6]=menuItemStr6;
	menuItemList[7]=menuItemStr7;
	menuItemList[8]=menuItemStr8;
	menuItemList[9]=menuItemStr9;
}

int8_t Game::titleScreen(const uint8_t* name){
	titleScreen(name, 0);
	return 1;
}

int8_t Game::titleScreenLogo(const uint8_t* logo){
	titleScreen(F(""), logo);
	return 1;
}

int8_t Game::titleScreen(){
	titleScreen(F(""));
	return 1;
}

int8_t Game::titleScreen(const uint8_t*  name, const uint8_t *logo)
{
	if(startMenuTimer)
	{
		display.fontSize = 1;
		display.textWrap = false;
		display.persistence = false;
		display.setColor(BLACK);
		display.setFont(font5x7);
		while(1)
		{
			
			if(update())
			{
				
				if(state!=DIS_STATE_VER)
				{
					display.update();
					display.clear();
					return 1;

				}	
				
				uint8_t logoOffset = pgm_read_byte(name)?display.fontHeight:0; //add an offset the logo when there is a name to display
				//draw graphics
				#if LCDWIDTH == LCDWIDTH_NOROT
				display.drawBitmap(0,0, gamebuinoLogo);
				if(logo){
					display.drawBitmap(0, 12+logoOffset, logo);
				}
				display.cursorX = 0;
				display.cursorY = 18; 
				#else
				display.drawBitmap(7,0, gamebuinoLogo);
				display.drawBitmap(-41,12,gamebuinoLogo);
				if(logo){
					display.drawBitmap(0, 24+logoOffset, logo);
				}
				display.cursorX = 0;
				display.cursorY = 24; 
				#endif
				display.print(name);
				
				}
			}
	}
}
bool Game::update() {
	if (((nextFrameMillis - millis()) > timePerFrame) && frameEndMicros) 
	{ //if time to render a new frame is reached and the frame end has ran once
		nextFrameMillis = millis() + (uint32_t)timePerFrame;
		frameCount++;

		frameEndMicros = 0;
		return true;

	} else {
		if (!frameEndMicros) { //runs once at the end of the frame		
			updatePopup();	

			display.update(); //send the buffer to the screen
			if(!display.persistence)
			display.clear(); //clear the buffer
			frameEndMicros=10000;   //移植过来，原来是获取微妙值，现在直接写个固定值
//			frameDurationMicros = frameEndMicros - frameStartMicros;
		}
		return false;
	}
}
void Game::popup(const uint8_t* text, uint8_t duration){
#if (ENABLE_GUI > 0)
	popupText = text;
	popupTimeLeft = duration+12;
#endif
}
void Game::updatePopup(){
#if (ENABLE_GUI > 0)
	if (popupTimeLeft){
		uint8_t yOffset = 0;
		if(popupTimeLeft<12){
			yOffset = 12-popupTimeLeft;
		}
		display.fontSize = 1;
		display.setColor(WHITE);
		display.fillRoundRect(0,LCDHEIGHT-display.fontHeight+yOffset-3,84,display.fontHeight+3,3);
		display.setColor(BLACK);
		display.drawRoundRect(0,LCDHEIGHT-display.fontHeight+yOffset-3,84,display.fontHeight+3,3);
		display.cursorX = 4;
		display.cursorY = LCDHEIGHT-display.fontHeight+yOffset-1;
		display.print(popupText);
		popupTimeLeft--;
	}
#endif
}

bool Game::settingsAvailable(){
//	if(pgm_read_word(SETTINGS_PAGE) == SETTINGS_TOKEN)
//	return true;
//	else
	return false;
}

void Game::readSettings(){
	if(settingsAvailable()){
		display.contrast = pgm_read_byte(SETTINGS_PAGE+OFFSET_CONTRAST);
		startMenuTimer = pgm_read_byte(SETTINGS_PAGE+OFFSET_START_MENU_TIMER);		
	}
	else
	{
		display.contrast = SCR_CONTRAST;				
		startMenuTimer = START_MENU_TIMER;
	}
}


void Game::getDefaultName(char* string){
	if(settingsAvailable()){	
		for(uint8_t i=0; i<USERNAME_LENGTH; i++){
			string[i] = (char)pgm_read_byte(SETTINGS_PAGE+OFFSET_USERNAME+i);
		}
	}
}

bool Game::collidePointRect(int16_t x1, int16_t y1 ,int16_t x2 ,int16_t y2, int16_t w, int16_t h){
	if((x1>=x2)&&(x1<x2+w))
	if((y1>=y2)&&(y1<y2+h))
	return true;
	return false;
}

bool Game::collideRectRect(int16_t x1, int16_t y1, int16_t w1, int16_t h1 ,int16_t x2 ,int16_t y2, int16_t w2, int16_t h2){
  return !( x2     >=  x1+w1  || 
            x2+w2  <=  x1     || 
            y2     >=  y1+h1  ||
            y2+h2  <=  y1     );
}

bool Game::collideBitmapBitmap(int16_t x1, int16_t y1, const uint8_t* b1, int16_t x2, int16_t y2, const uint8_t* b2){
  int16_t w1 = pgm_read_byte(b1);
  int16_t h1 = pgm_read_byte(b1 + 1);
  int16_t w2 = pgm_read_byte(b2);
  int16_t h2 = pgm_read_byte(b2 + 1);

  if(collideRectRect(x1, y1, w1, h1, x2, y2, w2, h2) == false){
    return false;
  }
  
  int16_t xmin = (x1>=x2)? 0 : x2-x1;
  int16_t ymin = (y1>=y2)? 0 : y2-y1;
  int16_t xmax = (x1+w1>=x2+w2)? x2+w2-x1 : w1;
  int16_t ymax = (y1+h1>=y2+h2)? y2+h2-y1 : h1;
  for(uint8_t y = ymin; y < ymax; y++){
    for(uint8_t x = xmin; x < xmax; x++){
      if(display.getBitmapPixel(b1, x, y) && display.getBitmapPixel(b2, x1+x-x2, y1+y-y2)){
        return true;
      }
    }
  }
  return false;
}

int8_t Game::menu() { 
#if (ENABLE_GUI > 0)
	display.persistence = false;
	int8_t currentY = LCDHEIGHT;
	int8_t targetY = 0;
	bool exit = false;
		
//	memcpy(menuItemStr0,F("111"),4);
//	memcpy(menuItemStr1,F("222"),4);
//	memcpy(menuItemStr2,F("333"),4);
//	memcpy(menuItemStr3,F("444"),4);
//	memcpy(menuItemStr4,F("555"),4);
	while (1) {
		if (update()) {
				uint8_t tmpCmd=user_i2cGetCmd();
			
				if(state!=DIS_STATE_MENU)
				{
					exit=true;
					targetY = - display.fontHeight * menuItemNumber - 2; //send the menu out of the screen
				}
				
				if(exit==false)
				{					
					if(tmpCmd==CMD_UP)
					{
						menuactiveItem--;
					}
					else if(tmpCmd==CMD_DOWN)
					{
						menuactiveItem++;
					}
					else if(tmpCmd==CMD_NUMBER)
					{
						if(cache[0]>=MENU_MAX_ITEM)
						{
							cache[0]=0;
						}
						menuactiveItem=cache[0];
					}	
					if (menuactiveItem == menuItemNumber) menuactiveItem = 0;
					if (menuactiveItem < 0) menuactiveItem = menuItemNumber - 1;
					targetY = -display.fontHeight * menuactiveItem + (display.fontHeight+4); //center the menu on the active item					
				}
				else return 1;
				

			
			//draw a fancy menu
			currentY = (currentY + targetY) / 2;
			display.cursorX = 0;
			display.cursorY = currentY;
			display.fontSize = 1;
			display.textWrap = false;
			for (uint8_t i = 0; i < menuItemNumber; i++) {
				if (i == menuactiveItem){
					display.cursorX = 3;
					display.cursorY = currentY + display.fontHeight * menuactiveItem;
				}
				display.println((uint8_t *)*(menuItemList+i));
			}
			
			//display.fillRect(0, currentY + 3 + 8 * activeItem, 2, 2, BLACK);
			display.setColor(WHITE);
			display.drawFastHLine(0, currentY + display.fontHeight * menuactiveItem-1 , LCDWIDTH);
			display.setColor(BLACK);
			if(tmpCmd==CMD_RIGHT||tmpCmd==CMD_START)
			{
					display.drawRoundRect(1, currentY + display.fontHeight * menuactiveItem -1, LCDWIDTH-2, (display.fontHeight+1), 3);
			}
			display.drawRoundRect(0, currentY + display.fontHeight * menuactiveItem -2, LCDWIDTH, (display.fontHeight+3), 3);
		}
	}
#else
	return 0;
#endif
}


//绘图模式
int8_t Game::draw()
{	
	display.clear();
	display.persistence=true;   //保留每一次绘画内容
	while(1)
	{		
		if(update())
		{
				uint8_t tmpCmd=user_i2cGetCmd();
				if(state!=DIS_STATE_DRAW)
				{
					display.clear();
					display.update();
					return 1;

				}				
		}
		
	}
}
int8_t Game::saver()
{
	int ball_x = LCDWIDTH/2; //set the horizontal position to the middle of the screen
	int ball_y = LCDHEIGHT/2; //vertical position
	int ball_vx = 1; //horizontal velocity
	int ball_vy = 1; //vertical velocity
	int ball_size = 6; //the size of the ball in number of pixels

	display.clear();
	display.persistence=false;   //不保留每一次绘画内容
	while(1)
	{		
		if(update())
		{
				uint8_t tmpCmd=user_i2cGetCmd();
				if(state!=DIS_STATE_SAVER)
				{
					display.clear();
					display.update();
					return 1;

				}			
				//add the speed of the ball to its position
				ball_x = ball_x + ball_vx;
				ball_y = ball_y + ball_vy;
				
				//check that the ball is not going out of the screen
				//if the ball is touching the left side of the screen
				if(ball_x < 0){
					//change the direction of the horizontal speed
					ball_vx = -ball_vx;
					//play a preset "tick" sound when the ball hits the border
				}
				//if the ball is touching the right side
				if((ball_x + ball_size) > LCDWIDTH){
					ball_vx = -ball_vx;
				}
				//if the ball is touching the top side
				if(ball_y < 0){
					ball_vy = -ball_vy;
				}
				//if the ball is touching the down side
				if((ball_y + ball_size) > LCDHEIGHT){
					ball_vy = -ball_vy;
				}
				
				//draw the ball on the screen
				display.fillRect(ball_x, ball_y, ball_size, ball_size);				
		}
		
	}

}
void Game::stateCheck()
{
	while(1)
	{
		switch (state) 
		{
			case DIS_STATE_DRAW:
				draw();
				break;
			case DIS_STATE_VER:
				titleScreen(F(" SOFT-VER:1.0"));
				break;
			case DIS_STATE_MENU: 
				menu(); 
				break;
			case DIS_STATE_GAME1:
				game1();
				break;
			case DIS_STATE_SAVER:
				saver();
				break;
			case DIS_STATE_GAME2:
				game2();
				break;
			case DIS_STATE_GAME3:
				game3();
				break;
				
		}
	}
}
